"""Database structures."""
import math

mult = 10000000.0

def checkLat(value):
	if not value or not value.isdigit():
		raise SyntaxError(_("no latitude or syntax error. Only numbers are allowed"))
	if math.fabs(float(value)/mult)>=90:
		raise ValueError (_("latitude is incorrect (greater than 90 degrees)"))
	return int(value)

def checkLon(value):
	if not value or not value.isdigit():
		raise SyntaxError(_("no longitude or syntax error. Only numbers are allowed"))
	if math.fabs(float(value)/mult)>=180:
		raise ValueError (_("longitude is incorrect (greater than 180 degrees)"))
	return int(value)

def checkLabel(string,value,max=75):
	if len(value)>max:
		raise ValueError(_("Too many characters in %s (%d instead of %d maximum allowed)")%(string,len(value),max))
	return value

def checkInt(string,value,max=0):
	if not value or not value.isdigit():
		raise SyntaxError(_("no %s or syntax error. Only numbers are allowed")%string)
	if max!=0 and int(value)>max:
		raise ValueError(_("Incorrect %s")%string)
	return int(value)

def checkUserID(value,name="user ID"):
	value=checkInt(name,value,99999)
	if value<10:
		raise ValueError(_("Incorrect %s (lesser than 10)")%name)
	return value

class DBRecord(dict):
	name=""
	fields=[]
	def __init__(self,**qwargs):
		self.update(qwargs)

class PointRecord(DBRecord):
	name="point"
	fields=["name","latitude","longitude","accuracy","satellites","priority","userid","id"]

	def isPrivate(self):
		return self["priority"]&1 == 1

	def isRestricted(self):
		return self["priority"]&2 == 2

	def isDeleted(self):
		return self["priority"]&4 == 4

	def __setitem__(self,item,value):
		if item=="name":
			super(PointRecord,self).__setitem__("name",checkLabel("name",value))
		elif item=="latitude":
			super(PointRecord,self).__setitem__("latitude",checkLat(value))
		elif item=="longitude":
			super(PointRecord,self).__setitem__("longitude",checkLon(value))
		elif item=="accuracy":
			super(PointRecord,self).__setitem__("accuracy",checkInt("accuracy",value,100))
		elif item =="satellites":
			super(PointRecord,self).__setitem__("satellites",checkInt("number of satellites",value,12))
		elif item =="priority":
			super(PointRecord,self).__setitem__("priority",checkInt("priority",value,7))
		elif item =="userid":
			super(PointRecord,self).__setitem__("userid",checkUserID(value))
		elif item =="id":
			super(PointRecord,self).__setitem__("id",checkInt("ID",value))
		else:
			raise LookupError(_("Field \"%s\" is not supported")%item)

class CellRecord(DBRecord):
	name="cell"
	fields=["name","id","mcc","mnc","locationareacode","cellid","userid"]

	def __setitem__(self,item,value):
		if item=="name":
			super(CellRecord,self).__setitem__("name",checkLabel("name",value))
		elif item =="id":
			super(CellRecord,self).__setitem__("id",checkInt("ID",value))
		elif item =="mcc":
			super(CellRecord,self).__setitem__("mcc",checkInt("mobile country code",value))
		elif item =="mnc":
			super(CellRecord,self).__setitem__("mnc",checkInt("mobile network code",value))
		elif item =="locationareacode":
			super(CellRecord,self).__setitem__("locationareacode",checkInt("location area code",value))
		elif item =="cellid":
			super(CellRecord,self).__setitem__("cellid",checkInt("cell id",value))
		elif item =="userid":
			super(CellRecord,self).__setitem__("userid",checkUserID(value))
		else:
			raise LookupError(_("Field \"%s\" is not supported")%item)

class NetworkRecord(DBRecord):
	name="network"
	fields=["name","id","mcc","mnc","userid"]

	def __setitem__(self,item,value):
		if item=="name":
			super(NetworkRecord,self).__setitem__("name",checkLabel("name",value,30))
		elif item =="id":
			super(NetworkRecord,self).__setitem__("id",checkInt("ID",value))
		elif item =="mcc":
			super(NetworkRecord,self).__setitem__("mcc",checkInt("mobile country code",value))
		elif item =="mnc":
			super(NetworkRecord,self).__setitem__("mnc",checkInt("mobile network code",value))
		elif item =="userid":
			super(NetworkRecord,self).__setitem__("userid",checkUserID(value))
		else:
			raise LookupError(_("Field \"%s\" is not supported")%item)

class RelationRecord(DBRecord):
	name="relation"
	fields=["source","source_userid","source_type","dest","dest_userid","dest_type","userid"]

	def __setitem__(self,item,value):
		if item=="source":
			super(RelationRecord,self).__setitem__("source",checkInt("source",value))
		elif item =="source_userid":
			super(RelationRecord,self).__setitem__("source_userid",checkUserID(value,name="source user id"))
		elif item=="source_type":
			super(RelationRecord,self).__setitem__("source_type",checkInt("type of source",value))
		elif item=="dest":
			super(RelationRecord,self).__setitem__("dest",checkInt("destination",value))
		elif item =="dest_userid":
			super(RelationRecord,self).__setitem__("dest_userid",checkUserID(value,name="destination user id"))
		elif item=="dest_type":
			super(RelationRecord,self).__setitem__("dest_type",checkInt("type of destination",value))
		elif item =="userid":
			super(RelationRecord,self).__setitem__("userid",checkUserID(value))
		else:
			raise LookupError(_("Field \"%s\" is not supported")%item)

class DB:
	point=[]
	cell=[]
	network=[]
	relation=[]
	tables={
	"point":(PointRecord,point),
	"cell": (CellRecord,cell),
	"network": (NetworkRecord,network),
	"relation": (RelationRecord,relation)}

	@classmethod
	def tableToString(cls,recClass,records):
		s=u"table,%s\n"%recClass.name
		s+="%s\n"%",".join(recClass.fields)
		for r in records:
			text=["\"%s\""%r[field] if isinstance(r[field],basestring) else str(r[field]) for field in recClass.fields]
			s+="%s\n"%",".join(text)
		s+="\n"
		return s

	def tostring(self):
		s=u"#!lsdb\n"
		for recClass,table in self.tables.itervalues():
		 	if table !=[]:
				s+=self.tableToString(recClass,table)
		return s

	def writeToBuffer(self,buf):
		buf.write("#!lsdb\n")
		for recClass,table in self.tables.itervalues():
			if table ==[]: continue
			s=u"table,%s\n"%recClass.name
			s+="%s\n"%",".join(recClass.fields)
			buf.write(s)
			for r in table:
				text=["\"%s\""%r[field] if isinstance(r[field],basestring) else str(r[field]) for field in recClass.fields]
				buf.write("%s\n"%",".join(text))
			buf.write("\n")
